package dynamic.routing.config;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilderCustomizer;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map;


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryMysql",
        transactionManagerRef = "transactionManagerMysql",
        basePackages = {"dynamic.routing.dao.mysql"}
)
public class MysqlConfig {
    @Autowired
    @Qualifier("mysqlDataSource")
    private DataSource primaryDataSource;
    @Autowired
    private HibernateProperties hibernateProperties;

    @Autowired
    @Qualifier("mysqlJpaProperties")
    public JpaProperties mysqlJpaProperties;

    @Bean(name = "entityManagerFactoryBuilderMysql")
    public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
                                                                   ObjectProvider<PersistenceUnitManager> persistenceUnitManager,
                                                                   ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers,
                                                                   @Qualifier("mysqlJpaProperties") JpaProperties properties) {
        hibernateProperties.setDdlAuto("update");
        // 这里不知道为什么，因为设置h2为首选数据库，这里的方言读不到配置的值，需要手动设置才行。
        AbstractJpaVendorAdapter abstractJpaVendorAdapter= (AbstractJpaVendorAdapter) jpaVendorAdapter;
        abstractJpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL8Dialect");
        abstractJpaVendorAdapter.setDatabase(Database.MYSQL);

        EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(jpaVendorAdapter, properties.getProperties(), (PersistenceUnitManager)persistenceUnitManager.getIfAvailable());
        customizers.orderedStream().forEach((customizer) -> {
            customizer.customize(builder);
        });
        return builder;
    }

    @Bean(name = "entityManagerFactoryMysql")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryMysql(@Qualifier("entityManagerFactoryBuilderMysql") EntityManagerFactoryBuilder builder){
        Map<String, Object> propertiesMap= hibernateProperties.determineHibernateProperties(mysqlJpaProperties.getProperties(), new HibernateSettings());
        propertiesMap.put("hibernate.physical_naming_strategy", "org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
        //说明：驼峰与下划线命令策略，如果报 未知列名，可能是这个错误。
//        propertiesMap.put("hibernate.physical_naming_strategy", "org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy");
        return builder
                .dataSource(primaryDataSource)
                .properties(propertiesMap)
                .packages("dynamic.routing.entity.mysql")//实体类的位置
                .persistenceUnit("mysqlPersistenceUnit")
                .build();
    }

    @Bean(name = "entityManagerMysql")
    public EntityManager entityManager(@Qualifier("entityManagerFactoryBuilderMysql")EntityManagerFactoryBuilder builder){
        return entityManagerFactoryMysql(builder).getObject().createEntityManager();
    }

    @Bean(name = "transactionManagerMysql")
    PlatformTransactionManager transactionManagerPrimary(@Qualifier("entityManagerFactoryBuilderMysql")EntityManagerFactoryBuilder builder){
        return new JpaTransactionManager(entityManagerFactoryMysql(builder).getObject());
    }

}
